from fastapi import Depends, HTTPException, status, Request
from fastapi.security import OAuth2PasswordBearer
from fastapi.security.utils import get_authorization_scheme_param
from jose import JWTError, jwt
from sqlalchemy.orm import Session
from app.db.session import get_db
from app.schemas.user import UserOut
from app.services.user import UserService
from app.core.config import Settings
from loguru import logger

oauth2_scheme = OAuth2PasswordBearer(tokenUrl="auth/login")

# 添加令牌黑名单存储
token_blacklist = set()

async def add_to_blacklist(token: str):
    """将令牌加入黑名单"""
    token_blacklist.add(token)

async def is_token_blacklisted(token: str) -> bool:
    """检查令牌是否在黑名单中"""
    return token in token_blacklist

async def get_token_from_header_or_cookie(request: Request):
    # 1. 优先 Authorization header
    auth = request.headers.get("Authorization")
    if auth:
        scheme, param = get_authorization_scheme_param(auth)
        if scheme.lower() == "bearer":
            return param
    # 2. cookie: access_token
    token = request.cookies.get("access_token")
    if token:
        return token
    # 3. cookie: token
    token = request.cookies.get("token")
    if token:
        return token
    # 4. header: token
    token = request.headers.get("token")
    if token:
        return token
    # 5. 都没有则报错
    raise HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="Not authenticated",
        headers={"WWW-Authenticate": "Bearer"},
    )

async def get_current_user(
    token: str = Depends(get_token_from_header_or_cookie),
    db: Session = Depends(get_db)
) -> UserOut:
    credentials_exception = HTTPException(
        status_code=status.HTTP_401_UNAUTHORIZED,
        detail="无法验证凭据",
        headers={"WWW-Authenticate": "Bearer"},
    )
    # 先检查令牌是否在黑名单中
    if await is_token_blacklisted(token):
        raise credentials_exception

    try:
        payload = jwt.decode(
            token, 
            Settings.SECRET_KEY, 
            algorithms=[Settings.ALGORITHM]
        )
        email: str = payload.get("sub")
        if not email:  
            logger.error("没有邮箱")
            raise credentials_exception
    except JWTError as e:
        logger.error(f"错误类型: {type(e).__name__}")
        logger.error(f"错误详情: {str(e)}")
        raise credentials_exception
    user = UserService.get_user_by_email(db, email=email)
    if user is None:
        raise credentials_exception
    return UserOut.model_validate(user)

async def verify_token(token: str):
    try:
        payload = jwt.decode(
            token, 
            Settings.SECRET_KEY, 
            algorithms=[Settings.ALGORITHM]
        )
        email: str = payload.get("sub")
        if email is None:
            return None
    except JWTError:
        return None
        
    db = next(get_db())
    try:
        user = UserService.get_user_by_email(db, email)
        if user is None:
            return None
        return user
    finally:
        db.close()
